﻿using System;
using System.Web;
using System.Web.Caching;
using CacheItemPriority = System.Web.Caching.CacheItemPriority;

namespace CoreLibrary.Cache {

    public class WebCache : AbstractCache {
        
        public int TimeOutInMins { get; set; }

        public Action<string, object> OnExpired;
        public Action<string, object> OnRemoved;
        public Action<string, object> OnUnderUsed;
        public Action<string, object> OnDependencyChanged;

        protected override void OnInit() {
            Asserts.NotNull(HttpRuntime.Cache, "HttpContext Cache can not be null.");
        }

        protected override void OnStart()  {}
        protected override void OnStop()   {}
        protected override void OnDestroy(){}

        public WebCache() {
			TimeOutInMins = 3;
        }

	    public T Get<T>(string key, Func<T> itemCreator) {
            return Get(key, itemCreator, true);
        }

        protected override CacheItem<T> GetItem<T>(string key) {
            var data = HttpRuntime.Cache.Get(key);
            if (data == null || data is T == false) {
                return new CacheItem<T>(false, default(T)) {
                       Key = key
                };
            }
            return new CacheItem<T>(true,(T)data) {
                   Key = key
            };
        }

        public override void Remove(string key) {
            HttpRuntime.Cache.Remove(key);
        }

        public override void Put(string key, object value) {
            HttpRuntime.Cache.Insert(
                        key,
                        value,
                        null,
                        System.Web.Caching.Cache.NoAbsoluteExpiration,
                        System.Web.Caching.Cache.NoSlidingExpiration
            );
        }

        public override void Put(string key, object value, TimeSpan expiration) {
            HttpRuntime.Cache.Insert(
                        key, 
                        value, 
                        null, 
                        System.Web.Caching.Cache.NoAbsoluteExpiration,
                        expiration,
                        CacheItemPriority.High,
                        OnRemoval
            );
        }

        protected virtual void OnRemoval(string key, object value, CacheItemRemovedReason rason) {
            switch (rason) {
                case CacheItemRemovedReason.Expired : {
                    if (OnExpired != null) {
                        OnExpired(key, value);
                    }
                    break;
                }
                case CacheItemRemovedReason.Removed : {
                    if (OnRemoved != null) {
                        OnRemoved(key, value);
                    }
                    break;
                }
                case CacheItemRemovedReason.Underused : {
                    if (OnUnderUsed != null) {
                        OnUnderUsed(key, value);
                    }
                    break;
                }
                case CacheItemRemovedReason.DependencyChanged : {
                    if (OnDependencyChanged != null) {
                        OnDependencyChanged(key, value);
                    }
                    break;
                }
                default:{
                    // LogManager.GetCurrentClassLogger().Info("Removing object #[" + key + "]");
                    break;
                }
            }
        }

    }
}